#ifndef QDATASESSION_H
#define QDATASESSION_H

#include <QObject>
#include <QDebug>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QSqlError>

#include "qdataset.h"
#include "qdatatable.h"

// 数据库连接、操作类封装
class QDataSession
{
public:
    explicit QDataSession();
    QDataSession(QSqlDatabase db);
    virtual ~QDataSession();

public:
    // 打开连接
    bool open();
    // 断开连接
    bool close(bool commit=false);
    // 是否连接
    bool isOpen();
    // 是否有效
    bool isValid();

    // 开始事务
    bool transaction();
    // 回滚事务
    bool rollback();
    // 提交
    bool commit();

    // 打印 sql
    void print(QSqlQuery);
    // 打印错误
    void print(QSqlError);

public:
    // 枚举表
    QStringList showTable();
    // 是否包含表
    bool hasTable(QString name);

public:
    // 执行 sql,适用于 sql 返回多个结果集
    // 返回 QDataSet
    QDataSet list(QString sql,QVariantList args=QVariantList());
    // 执行 sql,适用于 sql 返回一个结果集
    // 返回 QDataTable
    QDataTable table(QString sql,QVariantList args);
    // 执行 sql
    // sql 执行没有错,则返回 true
    bool excute(QString sql,QVariantList args=QVariantList());

    // 查询单表
    QDataTable table(QString tableName,QString where=QString(),QString orderBy=QString());
    QDataTable table(QString tableName,QString where,QStringList orderBy);

    QDataTable table(QString tableName,QVariantMap where,QString orderBy=QString());
    QDataTable table(QString tableName,QVariantMap where,QStringList orderBy);

    QDataTable table(QString tableName,QStringList columns,QString where=QString(),QString orderBy=QString());
    QDataTable table(QString tableName,QStringList columns,QString where,QStringList orderBy);

    QDataTable table(QString tableName,QStringList columns,QVariantMap where,QString orderBy=QString());
    QDataTable table(QString tableName,QStringList columns,QVariantMap where,QStringList orderBy);

    // 添加
    // 使用 data 的所有字段,使用时请确保 data 的字段与数据库一致
    bool add(QString tableName,QVariantMap data);
    // 指定字段从 data 中取值
    // 如果指定字段在 data 中不存在,则会使用 QVariant 做为值
    bool add(QString tableName,QStringList columns,QVariantMap data);
    // 适用于添加少量数据
    // 没有事务处理
    // 效率并不是很高,循环调用 add
    bool add(QString tableName,QList<QVariantMap> data);
    // 适用于添加少量数据
    // 没有事务处理
    // 效率一般,拼接 sql 方式
    bool add(QString tableName,QStringList columns,QList<QVariantMap> data);

    // 删除
    // sql 执行没有错,则返回 true
    bool remove(QString tableName,QString where=QString());
    // sql 执行没有错,则返回 true
    bool remove(QString tableName,QVariantMap where);

    // 更新
    // sql 执行没有错,则返回 true
    bool update(QString tableName,QVariantMap data,QString where);
    // sql 执行没有错,则返回 true
    bool update(QString tableName,QVariantMap data,QVariantMap where);
    // 如果指定字段在 data 中不存在,则会使用 QVariant 做为值
    // sql 执行没有错,则返回 true
    bool update(QString tableName,QStringList columns,QVariantMap data,QString where);
    // 如果指定字段在 data 中不存在,则会使用 QVariant 做为值
    // sql 执行没有错,则返回 true
    bool update(QString tableName,QStringList columns,QVariantMap data,QVariantMap where);

    // 统计数量
    int count(QString tableName,QString where=QString());
    int count(QString tableName,QVariantMap where);

    // 是否存在
    bool exist(QString tableName,QString where=QString());
    bool exist(QString tableName,QVariantMap where);

protected:
    // 创建查询
    virtual QSqlQuery create();
    // 绑定查询
    virtual void bind(QSqlQuery query,QVariantList args);

protected:
    QSqlDatabase connection;
};

class QLimitSession:public QDataSession{
public:
    explicit QLimitSession();
    QLimitSession(QSqlDatabase db);

    QDataTable limit(QString tableName,QString where,QString orderBy,QString limit);
    QDataTable limit(QString tableName,QString where,QStringList orderBy,QString limit);

    QDataTable limit(QString tableName,QVariantMap where,QString orderBy,QString limit);
    QDataTable limit(QString tableName,QVariantMap where,QStringList orderBy,QString limit);

    QDataTable limit(QString tableName,QStringList columns,QString where,QString orderBy,QString limit);
    QDataTable limit(QString tableName,QStringList columns,QString where,QStringList orderBy,QString limit);

    QDataTable limit(QString tableName,QStringList columns,QVariantMap where,QString orderBy,QString limit);
    QDataTable limit(QString tableName,QStringList columns,QVariantMap where,QStringList orderBy,QString limit);
};

#endif // QDATASESSION_H
